﻿
using Business.Base.Model;
using Business.Base.Service;
using Business.Base.Service.Create;
using Configuration;
using PLC.Base;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Pumptester.ExperimentForms.Base
{
    public  partial  class BaseMainForm : Form
    {
        #region 私有变量
        private Form entryForm;
        private Experiment experiment = null;
        private EnvData currentEnvData = null;
        IChartDrawer chartDrawer;
        private ExperimentService experimentService;
        #endregion

        #region 保护的变量
        protected delegate void DataReadHandle(EnvData message);
        protected DataReadHandle dataReadHandle = null;
        protected DataGridView baseDataGridView;

        #endregion

        #region 保护的属性
        /// <summary>
        /// 基础服务对象
        /// </summary>     
        protected virtual ExperimentService ExperimentService { get { return experimentService; } }

        public IChartDrawer ChartDrawer { get => chartDrawer; set => chartDrawer = value; }


        #endregion
        
        #region 公有属性
        public Experiment Experiment     { get => experiment; set => experiment = value; }
        public EnvData    CurrentEnvData { get => currentEnvData; set => currentEnvData = value; }
        /// <summary>
        /// 初始界面的引用，当前界面关闭后会返回初始界面
        /// </summary>
        public Form EntryForm { get => entryForm; set => entryForm = value; }
    

        #endregion

        #region 初始化

        /*protected virtual ExperimentService initExcuteService()
        {
            return null;
        }*/
           
        public BaseMainForm()
            {
            InitializeComponent();
                        }

        public BaseMainForm(Experiment experiment)
                { 
            Log.LogHelper.LoggerMsg(Log.LogLevel.Info, $"[Form:]:Entry BaseMainForm，experiment={experiment?.ToString()}");
            this.experiment = experiment;
            InitializeComponent();
            Log.LogHelper.LoggerMsg(Log.LogLevel.Info, "[Form:]:finish InitializeComponent");
            this.experimentService = ServiceContainer.getInstance()[this.experiment.ExperimentType];
            Log.LogHelper.LoggerMsg(Log.LogLevel.Info, "before startReadThread");
            startReadThread();
            Log.LogHelper.LoggerMsg(Log.LogLevel.Info, "after startReadThread");

                }
            

        protected virtual void BaseDataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            this.refreshIdCell();
        }
        #endregion

        #region 定时读取数据,并且将变量展示在DataGridView上

        #region 私有变量
        private object lockObject = new object();
        // System.Timers.Timer timer = new System.Timers.Timer(1000); //设置时间间隔为5秒
        Thread threadReadData;
        // private String dnName;
        #endregion

        //protected DataReadHandle dataReadHandle =null;



        /// <summary>
        /// 接收硬件读取的数据，并且处理。
        /// </summary>
        /// <param name="data"></param>
        private void after_ReadData(EnvData data)
        {
            if (dataReadHandle == null)
            {
                return;
            }
            if (this.InvokeRequired)
            {
                try
                {
                    this.Invoke(dataReadHandle, new object[] { data });
                }
                catch 
                { 
                }
            }
 
        }
        #endregion

        /// <summary>
        /// 启动读取数据线程
        /// </summary>
        private void startReadThread()
        {
            if (GetParams() == null)
            {
                MessageBox.Show("当前试验参数中未提供电流变比,流量计位数和电压目标相位读取的信息!无法启动测试");
                return;
            }
            threadReadData = new Thread(new ThreadStart(ReadData));
            threadReadData.IsBackground = true;
            threadReadData.Start();
        }

        /// <summary>
        /// 定时读取硬件数据，并且将数据展示在界面上
        /// </summary>
        private void ReadData()
        {
            var timer = new System.Timers.Timer();
            timer.Interval = Config.DataGetInterval;
            timer.Enabled = true;
            timer.AutoReset = false;//设置是执行一次（false）还是一直执行(true)；  
            timer.Start();
            this.experimentService.StartRead();

            timer.Elapsed += (o, a) =>
            {
                try
                {

                    EnvData data = this.experimentService.FetchDataFromEnv(GetParams());
                    Log.LogHelper.LoggerMsg(Log.LogLevel.Info,"revive data:\r" + data.ToString());

                    after_ReadData(data);
                    Log.LogHelper.LoggerMsg(Log.LogLevel.Info, "after_ReadData called \n");
                    lock (lockObject)
        {
                        if (data != null)
                        {
                            this.currentEnvData = (EnvData)data.Clone();
        }
                    }
                    Log.LogHelper.LoggerMsg(Log.LogLevel.Info, "currentEnvData assigned! \n");
                    timer.Start();
                }
                catch(Exception ex)
        {
                    Log.LogHelper.LoggerMsg(Log.LogLevel.Error, "数据读取错误,详细信息：" + ex.ToString());
                    throw ex;
                    //System.Console.WriteLine(ex.ToString());
                }
            };
  
            //createExperiment(experiment);

            //启动算法,开始读取硬件的数据,注意，必须在定时器启动前开启
            //this.Service.initAlgorithm(this.experiment);
            

           // this.Service.SetIndexZero();
            //this.Service.ExperimentType = experiment.ExperimentType;
            //this.Service.PumpType = experiment.PumpType;
            //startReadThread();
            //启动定时器读取PLC数据
            //timerData.Tick += TimerData_Tick;
            //timerData.Interval = Config.DataGetInterval;
            // timerData.Start();
        }


        

        #region 抽象方法和属性


        /// <summary>
        /// 从硬件获取数据，并且返回Record记录
        /// </summary>
        /// <returns>Record数据</returns>
        private ExperimentRecord fetchRecordFromEnvData()
        {
            EnvData data = null;
            lock (lockObject)
            {
                if (CurrentEnvData != null)
                {
                    data = (EnvData)this.CurrentEnvData.Clone();
                }
            }
            return (data == null) ? null : assignEvnDataToRecord(data);
        }

        protected virtual DynamicParams GetParams()
        {
            return null;
        }

        /// <summary>
        /// 从硬件获取数据后，转化成record
        /// </summary>
        /// <param name="data">从硬件获取的数据</param>
        /// <returns>返回Record对象</returns>
        protected virtual ExperimentRecord assignEvnDataToRecord(EnvData data)
        {

            ExperimentRecord record = this.experimentService.CaculateDataFromRecord(this.experiment, data);
            this.experimentService.FetchData();
            return record;
        }




        /// <summary>
        /// 获取数据，并且采集到DataGridView
        /// </summary>
        private void fetchRecordAndShowinDataGridView()
        {
            ExperimentRecord record = fetchRecordFromEnvData();
            if (record.WorkingSpeed - 0 < Double.Epsilon)
        {
                MessageBox.Show("当前采集的转速为0，请确认采集的硬件是否运行！");
                return;
            }
            record.RecordTime = DateTime.Now;
            this.Experiment.RecordList.Add(record);
            ShowRecordinDataGridView(record);
        }

        /// <summary>
        /// 在界面上展示记录
        /// </summary>
        /// <param name="record">新增的记录</param>
        protected virtual void ShowRecordinDataGridView(ExperimentRecord record)
        { }

        #endregion

        #region 试验数据生命周期管理

        /// <summary>
        /// 退出试验，退出前询问
        /// </summary>
        private void cancleAndExitExpriment()
        {
            if (DialogResult.OK == MessageBox.Show("退出后，数据将不保存", "退出试验", MessageBoxButtons.OKCancel))
            {
                //this.timerData.Stop();
                this.experimentService.DeleteExperiment(this.Experiment);
                this.Close();    
            }
        }

        /// <summary>
        /// 创建试验
        /// </summary>
        /// <param name="experiment"></param>
        private void createExperiment(Experiment experiment)
        {
            
            this.experimentService.SaveExperiment(experiment);
            //this.toolStripStatusLabelCode.Text = experiment.ExperimentCode;
            //this.toolStripStatusLabelProduct.Text = experiment.;
            //this.toolStripStatusLabelOwner.Text = experiment.ExperimentOwner;
        }

        /// <summary>
        /// 结束试验
        /// </summary>
        /// <returns>返回是否退出，不管是否保存</returns>
        private void FinishExperiment()
        {
            if (this.Experiment.RecordList.Count <= 3)
            {
                if (DialogResult.OK == MessageBox.Show("采集数据太少无法给出准确的结果!", "提示", MessageBoxButtons.OK))
        {
                    return ;
                }
        }
            else
            {
                if (DialogResult.Yes == MessageBox.Show("是否保存数据？", "退出试验", MessageBoxButtons.YesNo))
                {
                    this.experimentService.EndRead();
                    this.experimentService.CaculateExperimentResult(ref this.experiment);

                    this.experimentService.FinishExperiment(this.Experiment);
                    if (DialogResult.Yes == MessageBox.Show("报告已生成，是否打开？", "打开报告", MessageBoxButtons.YesNo))
        {
                        System.Diagnostics.Process.Start(experiment.FilePath);
                    }
                    this.Close();
                    return ;
                }
            }
            return ;
 
        }

        #endregion
        
        #region 报表展示



        /// <summary>
        /// 根据ChartData绘制报表
        /// </summary>
        /// <param name="chartData">绘制报表所需要的数据封装</param>
        protected virtual void DrawChart(BaseChartData chartData)
        { 
            
        }

        /// <summary>
        /// 清除报表
        /// </summary>
        protected virtual void ClearChart()
        { 
        }


        /// <summary>
        /// 每次获取数据的时候，用于重新计算和绘制报表，暂时放在主类中。
        /// </summary>
        protected virtual void CaculateAndReDrawReport()
        {

            BaseChartData chartData = this.experimentService.CaculateChartData(this.Experiment);
            if (chartData != null)
            {
                ClearChart();
                DrawChart(chartData);
            }
            else
            {
                ClearChart();
            }
        }

        #endregion

        #region 基础方法
        /// <summary>
        /// 刷新dataGridView的数据
        /// </summary>
        protected void refreshIdCell()
        {
            for (int i = 0; i < this.baseDataGridView.Rows.Count; i++)
            {
                this.baseDataGridView.Rows[i].Cells[0].Value = i + 1;
            }
        }

        

        #region 删除记录
        /// <summary>
        /// 删除选中的记录
        /// </summary>
        protected virtual void DeleteSelectRecord()
        {

            DataGridViewSelectedRowCollection selectedRows = this.baseDataGridView.SelectedRows;

            if (selectedRows.Count == 0)
            {
                return;
        }

            int[] ids = new int[selectedRows.Count];

            for (int i = 0; i < selectedRows.Count; i++)
            {
                if (selectedRows[i].Tag == null)
                {
                    ids[i] = -1;
                    continue;
                }
                ExperimentRecord record = (ExperimentRecord)selectedRows[i].Tag;
                ids[i] = record.Id;
                this.baseDataGridView.Rows.Remove(selectedRows[i]);
                this.Experiment.RecordList.Remove(record);
                }
            this.experimentService.RemoveExperimentRecordByIds(ids);
            this.CaculateAndReDrawReport();
            this.baseDataGridView.ClearSelection();
            refreshIdCell();
            }

        /// <summary>
        /// 删除所有的记录
        /// </summary>
        protected virtual void DeleteAllRecord()
            {
            for (int i = 0; i < this.baseDataGridView.Rows.Count; i++)
                {
                object tag = this.baseDataGridView.Rows[i].Tag;
                if (tag != null)
                    {
                    this.baseDataGridView.Rows[i].Selected = true;
            }
            //return false;
            
        }
            DeleteSelectRecord();
        }
        #endregion
       
        #endregion


        #region 事件

        private void toolStripFetchDataButton_Click(object sender, EventArgs e)
        {
            //this.Service.ReadNext();
            if (this.experiment.RecordList.Count >= 15)
            {
                MessageBox.Show("一个试验最多只能采集15条数据！", "提示", MessageBoxButtons.OK);
                {
                    return;
        }
            }
            fetchRecordAndShowinDataGridView();
        }

        private void BaseMainForm_Load(object sender, EventArgs e)
        {        
            //fetchRecordAndShowinDataGridView();
        }
                

        private void toolStripDeleteButton_Click(object sender, EventArgs e)
        {
            if (DialogResult.OK == MessageBox.Show("是否删除选中的记录", "确认删除", MessageBoxButtons.OKCancel))
            {
                DeleteSelectRecord();
            }
        }

        private void toolStripButtonCancle_Click(object sender, EventArgs e)
        {
            this.cancleAndExitExpriment();

        }

        private void toolStripClearButton_Click(object sender, EventArgs e)
        {
            if (DialogResult.OK == MessageBox.Show("是否删除所有记录", "确认删除", MessageBoxButtons.OKCancel))
            {
                DeleteAllRecord();
            }
        }

        private void toolStripFinishButton_Click(object sender, EventArgs e)
        {            
            this.FinishExperiment();
        }

 
        private void BaseMainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.experimentService.EndRead();
        }

        #endregion

        protected virtual DialogResult ShowEditDialog()
        {
            return DialogResult.Cancel;
        }
            
        private void toolStripBtnExperimentInfo_Click(object sender, EventArgs e)
        {
            if(ShowEditDialog()==DialogResult.OK)
            {
                //this.experimentService.UpdateExperiment(this.experiment);
                this.CaculateAndReDrawReport();
            }

        }
    }
}
